package com.kehutong.wwin.service.service;

import com.kehutong.wwin.service.entity.Corp;
import com.kehutong.wwin.service.entity.Suite;
import com.kehutong.wwin.service.util.WwInHttpClient;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.util.CallBack;
import org.coraframework.util.Objects;

import java.time.LocalDateTime;

/**
 * @author: liukunlong
 * @date: 2021-03-30 20:31
 */
@WebService("/wwin-service/suite")
public class SuiteService {
    private static final Logger logger = LoggerFactory.getLogger(SuiteService.class);

    @Inject
    private JdbcSession jdbcSession;

    @Inject
    private WwInHttpClient httpClient;

    @ReqMapping("/get")
    public Object get(Suite item) {
        return item;
    }

    @ReqMapping("/list")
    public Page<Suite> list(JSONObject jsonObject) {
        return jdbcSession.findPage(Suite.class)
                .eq(jsonObject, "appId")
                .like(jsonObject, "name")
                .eq("deleted", false)
                .page(jsonObject)
                .exe();
    }


    /**
     * 根据企业编号获取企业内建应用信息(一个企业只能有一个内建应用？)
     * @param corpId
     * @return
     */
    public Suite getSuiteByCorpId(String corpId) {
        return jdbcSession.findOne(Suite.class)
                .eq("corpId", corpId)
                .eq("deleted", false)
                .exe();
    }
    /**
     * 获取应用AccessToken
     * @param suite 应用对象
     * @return 应用AccessToken
     * @throws Exception 异常
     */
    public String getAppAccessToken(Suite suite) throws Exception {
        if(logger.isInfoEnabled()){
            logger.info("getAppAccessToken:企业微信联系人Token失效时间 is: {}",suite.getAccessTokenExpiredTime());
        }
        if (valid(suite.getAccessTokenExpiredTime())) {
            if(logger.isInfoEnabled()) {
                logger.info("getAppAccessToken:企业微信联系人Token时间没有失效,contactAccessToken is: {}",suite.getAccessToken());
            }
            return suite.getAccessToken();
        }

        getAccessToken(suite.getId(), suite.getSecret(), json -> {
            suite.setAccessToken(json.getString("access_token"));
            suite.setAccessTokenExpiredTime(LocalDateTime.now().plusSeconds(json.getLong("expires_in")));
            jdbcSession.updateById(suite);
            if(logger.isDebugEnabled()){
                logger.debug("回调更新企业联系人Token信息,Corp: {}",suite);
            }
        });

        return suite.getAccessToken();
    }

    /**
     * 获取应用的AccessToken
     * @param corpid 企业ID，
     * @param secret 应用的凭证密钥
     * @param call 回调
     * @throws Exception 异常
     */
    private void getAccessToken(final String corpid, final String secret, CallBack<JSONObject> call) throws Exception {
        if (Objects.nonEmpty(corpid) && Objects.nonEmpty(secret)) {
            if(logger.isInfoEnabled()){
                logger.info("getAccessToken:调用企业微信获取应用Token信息,corpid is {} and secret is {}",corpid,secret);
            }
            JSONObject jsonObject = httpClient.get("/cgi-bin/gettoken", http -> {
                http.addParam("corpid", corpid);
                http.addParam("corpsecret", secret);
            });

            if(logger.isInfoEnabled()){
                logger.info("getAccessToken:调用企业微信获取应用Token信息结果是{}",jsonObject.toJSONString());
            }
            if (jsonObject.getIntValue("errcode") == 0) {
                if(logger.isInfoEnabled()){
                    logger.info("getAccessToken:执行企业微信获取应用Token信息回调");
                }
                call.call(jsonObject);
            }else{
                logger.warn("getAccessToken:低啊用企业微信获取应用Token信息失败,错误信息是 {}",jsonObject.toJSONString());
            }
        }
    }

    static boolean valid(LocalDateTime localDateTime) {
        if (Objects.isNull(localDateTime)) {
            return false;
        }

        return localDateTime.isAfter(LocalDateTime.now());
    }
}
